package com.activiti.dao.service.spring;


import com.activiti.dao.ActivitiDao;
import com.activiti.dao.model.Activiti_TaskCount;
import com.activiti.dao.model.Activiti_TaskInfo;
import com.activiti.dao.model.Activiti_TaskInfoRO;
import com.activiti.dao.model.TaskVo;
import com.activiti.dao.service.ActivitiService;
import com.erp.hr.dao.model.HrStaffDepartmentVO;
import com.erp.hr.dao.model.HrStaffInfoRO;
import com.erp.hr.service.HrCommonService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.TaskListener;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
import org.activiti.engine.impl.javax.el.ExpressionFactory;
import org.activiti.engine.impl.javax.el.ValueExpression;
import org.activiti.engine.impl.juel.ExpressionFactoryImpl;
import org.activiti.engine.impl.juel.SimpleContext;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmActivity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.task.TaskDefinition;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.lang.StringUtils;
import org.redragon.framework.hibernate.model.Pages;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.InputStream;
import java.util.*;

@Service
@Transactional(rollbackFor=Exception.class)
public class ActivitiServiceImpl implements ActivitiService, TaskListener {
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private ActivitiDao activitiDao;
    @Autowired
    private HrCommonService hrCommonService;

    private String[] userList;

    public String[] getUserList() {
        return userList;
    }

    public void setUserList(String[] userListParm) {
        this.userList = userListParm;
    }

    @Override
    public ProcessInstance erpStartProcessInstance(String processDefinitionKey,String businessKey,Map params,String busiId) {
        // 根据流程定义key启动流程
        ProcessInstance processInstance =   runtimeService.startProcessInstanceByKey(processDefinitionKey,businessKey,params);
        System.out.println(" 流 程 定 义 id ： " + processInstance.getProcessDefinitionId());
        System.out.println("流程实例id：" + processInstance.getId());
        System.out.println("当前活动Id：" + processInstance.getActivityId());
        return processInstance;
    }

    @Override
    public void  deleteProcessInstance(String processInstanceId){
        //判断该流程实例是否结束，未结束和结束两者删除表的信息是不一样的。
        ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if(pi==null){
            //该流程实例已经完成了
            historyService.deleteHistoricProcessInstance(processInstanceId);
        }else{
            //该流程实例未结束的
            runtimeService.deleteProcessInstance(processInstanceId,"");
            historyService.deleteHistoricProcessInstance(processInstanceId);
        }
    }

    @Override
    public List<TaskVo> erpFindPersonalTaskList(HrStaffInfoRO staffInfo) {
        // 创建TaskService
        List<Task> list = taskService.createTaskQuery().orderByTaskCreateTime().desc().includeProcessVariables().taskAssignee(staffInfo.getStaffCode()).active().list();
        List<TaskVo> tasklist  = new ArrayList<>();
        for (Task task : list) {
            System.out.println("----------------------------");
            System.out.println("流程实例id：" + task.getProcessInstanceId());
            System.out.println("任务id：" + task.getId());
            System.out.println("任务负责人：" + task.getAssignee());
            System.out.println("任务名称：" + task.getName());
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
            TaskVo taskVo = new TaskVo();
            taskVo.setId(task.getId());
            taskVo.setProcessInstanceId(task.getProcessInstanceId());
            taskVo.setName(task.getName());
            taskVo.setCreateTime(task.getCreateTime());
            taskVo.setAssignee(staffInfo.getStaffName());
            taskVo.setCompanyName(staffInfo.getCompanyName());
            taskVo.setDepartmentName(staffInfo.getDepartmentName());
            taskVo.setBusinessUrl(processInstance.getBusinessKey());
            tasklist.add(taskVo);
        }
        return tasklist;
    }

    @Override
    public List<TaskVo> erpFindPersonalTaskListByCount(HrStaffInfoRO staffInfo, int count) {
        // 创建TaskService
        if(staffInfo==null){return null;}
        List<Task> list = taskService.createTaskQuery().orderByTaskCreateTime().desc().includeProcessVariables().taskAssignee(staffInfo.getStaffCode()).active().list();
        List<TaskVo> tasklist  = new ArrayList<>();
        for (Task task : list) {
            System.out.println("----------------------------");
            System.out.println("流程实例id：" + task.getProcessInstanceId());
            System.out.println("任务id：" + task.getId());
            System.out.println("任务负责人：" + task.getAssignee());
            System.out.println("任务名称：" + task.getName());
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
            TaskVo taskVo = new TaskVo();
            taskVo.setId(task.getId());
            taskVo.setProcessInstanceId(task.getProcessInstanceId());
            taskVo.setName(task.getName());
            taskVo.setCreateTime(task.getCreateTime());
            taskVo.setAssignee(staffInfo.getStaffName());
            taskVo.setCompanyName(staffInfo.getCompanyName());
            taskVo.setDepartmentName(staffInfo.getDepartmentName());
            taskVo.setBusinessUrl(processInstance.getBusinessKey());
            tasklist.add(taskVo);
        }
        if(tasklist.size()<=count){
            return tasklist;
        }
        return tasklist.subList(0, count);
    }

    @Override
    public Task erpGetCurrentTask(String processInstanceId) {
        Task  task = taskService.createTaskQuery().orderByTaskCreateTime().desc().processInstanceId(processInstanceId).active().singleResult();
        //String taskId = task.getId();
        return task;
    }

    @Override
    public Task erpFindPersonalTaskByPid(String pid) {
        Task task = taskService.createTaskQuery().orderByTaskCreateTime().desc().processInstanceId(pid).active().singleResult();
        return task;
    }


    @Override
    public void erpCompletTask(String taskId,String condition,Map<String, String> nextapproverids) {
        if(nextapproverids!=null && nextapproverids.size()>0){
            if (condition != null && !"".equals(condition)) {
                //设置审批结果到流程变量中，用来控制流程走向
                Map<String, Object> variables = new HashMap<String, Object>();
                variables.put("condition", Integer.parseInt(condition));
                for(Map.Entry<String, String> entry : nextapproverids.entrySet()){
                    variables.put(entry.getKey(), Arrays.asList(entry.getValue().split(",")));
                    System.out.println(entry.getKey()+":"+entry.getValue());
                }
                taskService.setVariables(taskId, variables);
                taskService.complete(taskId);
                System.out.println("完成任务");
            }else{
                Map<String, Object> variables = new HashMap<String, Object>();
                for(Map.Entry<String, String> entry : nextapproverids.entrySet()){
                    variables.put(entry.getKey(), Arrays.asList(entry.getValue().split(",")));
                    System.out.println(entry.getKey()+":"+entry.getValue());
                }
                taskService.setVariables(taskId, variables);
                taskService.complete(taskId);
                System.out.println("完成任务");
            }
        }else {
            if (condition != null && !"".equals(condition)) {
                //设置审批结果到流程变量中，用来控制流程走向
                Map<String, Object> variables = new HashMap<String, Object>();
                variables.put("condition", Integer.parseInt(condition));
                taskService.setVariables(taskId, variables);
                taskService.complete(taskId);
                System.out.println("完成任务");
            }else{
                Map<String, Object> variables = new HashMap<String, Object>();
                taskService.setVariables(taskId, variables);
                taskService.complete(taskId);
                System.out.println("完成任务");
            }
        }

    }

    @Override
    //FileUtil.copyImageStream()将图片拷贝下来
    public InputStream getDefinitionImage(String processDefinitionId) {
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
        InputStream inputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getDiagramResourceName());
        return inputStream;
    }

    @Override
    public Task erpFindPersonalTaskActive(String processDefinitionId) {
        return  taskService.createTaskQuery().orderByTaskCreateTime().desc().processInstanceId(processDefinitionId).active().singleResult();
    }



    @Override
    public void insertDataObject(Activiti_TaskInfo activiti_taskInfo) {
        this.activitiDao.insertDataObject(activiti_taskInfo);
    }

    @Override
    public void updateDataObject(Activiti_TaskInfo activiti_taskInfo) {
        this.activitiDao.updateDataObject(activiti_taskInfo);
    }

    @Override
    public void insertOrUpdateDataObject(Activiti_TaskInfo activiti_taskInfo) {
        this.activitiDao.insertOrUpdateDataObject(activiti_taskInfo);
    }

    @Override
    public void deleteDataObject(Activiti_TaskInfo activiti_taskInfo) {
        this.activitiDao.deleteDataObject(activiti_taskInfo);
    }

    @Override
    public List<Activiti_TaskInfo> getDataObjects() {
        return  this.activitiDao.getDataObjects();
    }

    @Override
    public Activiti_TaskInfo getDataObject(int i) {
        return this.activitiDao.getDataObject(i);
    }

    @Override
    public Activiti_TaskInfo getDataObject(String s) {
        return this.activitiDao.getDataObject(s);
    }

    @Override
    public List<Activiti_TaskInfo> getDataObjects(Activiti_TaskInfo activiti_taskInfo) {
        return this.activitiDao.getDataObjects(activiti_taskInfo);
    }

    @Override
    public List<Activiti_TaskInfo> getDataObjects(Pages pages) {
        return this.activitiDao.getDataObjects(pages);
    }

    @Override
    public List<Activiti_TaskInfo> getDataObjects(Pages pages, Activiti_TaskInfo activiti_taskInfo) {
        return  this.activitiDao.getDataObjects(pages,activiti_taskInfo);
    }

    @Override
    public List<Map<String, Object>> getDataObjectsArray(Pages pages, Activiti_TaskInfo activiti_taskInfo) {
        return  this.activitiDao.getDataObjectsArray(pages,activiti_taskInfo);
    }

    @Override
    public List<Activiti_TaskInfo> getDataObjectsForDataAuth(String s, Pages pages, Activiti_TaskInfo activiti_taskInfo) {
        return  this.activitiDao.getDataObjectsForDataAuth(s,pages,activiti_taskInfo);
    }

    @Override
    public void notify(DelegateTask delegateTask) {
        delegateTask.addCandidateUsers(Arrays.asList(this.getUserList()));//完成多处理人的指定
    }

    @Override
    public List<String> getStaffByPosition(String departmentCode, String positionId) {
        /*StringBuffer codes = new StringBuffer();
        List<HrStaffDepartmentVO> HrStaffDepartmentVos=this.hrCommonService.getStaffByPosition(departmentCode,positionId);
        if(HrStaffDepartmentVos.size()>0){
            for(HrStaffDepartmentVO hrStaffDepartmentVO:HrStaffDepartmentVos){
                codes.append(hrStaffDepartmentVO.getStaff_code());
                codes.append(",");
            }
            System.out.println("合同签批流程参与者:"+codes.substring(0,codes.length()-1).toString());
            return codes.substring(0,codes.length()-1).toString();
        }
        return null;*/
        List<String> list = new ArrayList<>();
        List<HrStaffDepartmentVO> HrStaffDepartmentVos=this.hrCommonService.getStaffByPosition(departmentCode,positionId);
        if(HrStaffDepartmentVos.size()>0){
            for(HrStaffDepartmentVO hrStaffDepartmentVO:HrStaffDepartmentVos){
                list.add(hrStaffDepartmentVO.getStaff_code());
                System.out.println("合同签批流程参与者:"+hrStaffDepartmentVO.getStaff_code());
            }
            return list;
        }
        return null;
    }


    @Override
    public TaskDefinition getErpNextTask(String processInstanceId) {
        Task task = taskService.createTaskQuery().orderByTaskCreateTime().desc().processInstanceId(processInstanceId).active().singleResult();
        //然后根据当前任务获取当前流程的流程定义，然后根据流程定义获得所有的节点：
        ProcessDefinitionEntity def = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService).getDeployedProcessDefinition(task.getProcessDefinitionId());
        List<ActivityImpl> activitiList = def.getActivities();  //rs是指RepositoryService的实例
        //根据任务获取当前流程执行ID，执行实例以及当前流程节点的ID：
        String excId = task.getExecutionId();
        ExecutionEntity execution = (ExecutionEntity) runtimeService.createExecutionQuery().executionId(excId).singleResult();
        String activitiId = execution.getActivityId();
        //然后循环activitiList 并判断出当前流程所处节点，然后得到当前节点实例，根据节点实例获取所有从当前节点出发的路径，然后根据路径获得下一个节点实例：
        for (ActivityImpl activityImpl : activitiList) {
            String id = activityImpl.getId();
////                System.out.println("当前任务：" + activityImpl.getProperty("name")); //输出某个节点的某种属性
////                List<PvmTransition> outTransitions = activityImpl.getOutgoingTransitions();//获取从某个节点出来的所有线路
////                for (PvmTransition tr : outTransitions) {
////                    PvmActivity ac = tr.getDestination(); //获取线路的终点节点
////                    System.out.println("下一步任务任务：" + ac.getProperty("name"));
////                }
            if (activitiId.equals(id)) {
                //获取下一个节点信息
                return nextTaskDefinition(activityImpl, activityImpl.getId(), null, processInstanceId);
            }
        }
        return null;
    }
    private  TaskDefinition  nextTaskDefinition(ActivityImpl  activityImpl,  String  activityId,  String  elString,  String  processInstanceId){
        PvmActivity  ac  =  null;
        Object  s  =  null;
        //如果遍历节点为用户任务并且节点不是当前节点信息
        if("userTask".equals(activityImpl.getProperty("type"))  &&  !activityId.equals(activityImpl.getId())){
                //获取该节点下一个节点信息
                TaskDefinition  taskDefinition  =  ((UserTaskActivityBehavior)activityImpl.getActivityBehavior()).getTaskDefinition();
                return  taskDefinition;
        }else {
            //获取节点所有流向线路信息
            List<PvmTransition> outTransitions = activityImpl.getOutgoingTransitions();
            List<PvmTransition> outTransitionsTemp = null;
            for (PvmTransition tr : outTransitions) {
                ac = tr.getDestination();  //获取线路的终点节点
                //如果流向线路为排他网关
                if ("exclusiveGateway".equals(ac.getProperty("type"))) {
                    outTransitionsTemp = ac.getOutgoingTransitions();

                    //如果网关路线判断条件为空信息
                    if (StringUtils.isEmpty(elString)) {
                        //获取流程启动时设置的网关判断条件信息
                        elString = getGatewayCondition(ac.getId(), processInstanceId);
                    }

                    //如果排他网关只有一条线路信息
                    if (outTransitionsTemp.size() == 1) {
                        return nextTaskDefinition((ActivityImpl) outTransitionsTemp.get(0).getDestination(), activityId, elString, processInstanceId);
                    } else if (outTransitionsTemp.size() > 1) {    //如果排他网关有多条线路信息
                        for (PvmTransition tr1 : outTransitionsTemp) {
                            s = tr1.getProperty("conditionText");    //获取排他网关线路判断条件信息
                            //判断el表达式是否成立
                            if (isCondition(ac.getId(), StringUtils.trim(s.toString()), elString)) {
                                return nextTaskDefinition((ActivityImpl) tr1.getDestination(), activityId, elString, processInstanceId);
                            }
                        }
                    }
                } else if ("userTask".equals(ac.getProperty("type"))) {
                    return ((UserTaskActivityBehavior) ((ActivityImpl) ac).getActivityBehavior()).getTaskDefinition();
                } else {
                }
            }
            return null;
        }
    }

    public String getGatewayCondition(String gatewayId, String processInstanceId) {
        Execution execution = runtimeService.createExecutionQuery().processInstanceId(processInstanceId).singleResult();
        return runtimeService.getVariable(execution.getId(), gatewayId).toString();  
    }
                  

    public boolean isCondition(String key, String el, String value) {
        ExpressionFactory factory = new ExpressionFactoryImpl();
        SimpleContext context = new SimpleContext();    
        context.setVariable(key, factory.createValueExpression(value, String.class));    
        ValueExpression e = factory.createValueExpression(context, el, boolean.class);
        return (Boolean) e.getValue(context);  
    }  

    @Override
    public List<TaskVo> queryTaskInfo(List<TaskVo> taskVo){
        if(taskVo==null || taskVo.size()==0){return null;}
//        String procInstId="";
//        for(TaskVo taskVoTmp : taskVo){
//            procInstId=procInstId+taskVoTmp.getProcessInstanceId()+",";
//        }
        List<TaskVo> activitiList=new ArrayList();
//        procInstId=procInstId.substring(0,procInstId.length()-1);
        List<Activiti_TaskInfoRO> taskList=this.activitiDao.getDataObjects(taskVo);
        for(int i=0;i<taskVo.size();i++){
            TaskVo taskVoInfo=taskVo.get(i);
            for(int j=0;j<taskList.size();j++){
                Activiti_TaskInfoRO activiti_TaskInfo=taskList.get(j);
                if(taskVoInfo.getProcessInstanceId().equals(activiti_TaskInfo.getProc_inst_id())){
                    taskVoInfo.setBusinessTitle(activiti_TaskInfo.getProc_name());
                    taskVoInfo.setStatus(activiti_TaskInfo.getStatus());
                    activitiList.add(taskVoInfo);
                }
            }
        }
        return activitiList;
    }

    @Override
    public Activiti_TaskCount queryTaskCount(String staffCode) {
        return  this.activitiDao.queryTaskCount(staffCode);
    }

    @Override
    public Activiti_TaskInfo queryActivitiTaskInfoByPid(String pid){
        return this.activitiDao.queryActivitiTaskInfoByPid(pid);
    }

    @Override
    public Task erpGetCurrentTask(String processInstanceId, String staffCode) {
        Task task = taskService.createTaskQuery().taskAssignee(staffCode).orderByTaskCreateTime().desc().processInstanceId(processInstanceId).active().singleResult();
        return task;
    }

}